﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;

using BlueCMS.Core.Data;
using BlueCMS.Core.Data.Query.Clauses;
using BlueCMS.Core.Data.Query.Columns;
using BlueCMS.Core.Data.Query.Conditions;
using BlueCMS.Core.Data.Query.Tables;
using BlueCMS.Core.Providers;

namespace BlueCMS.Core.Data.Query.Generator
{
    public abstract partial class QueryGeneratorBase
    {
        protected virtual void GenerateFromStatement(FromClause clause, StringBuilder sb, Dictionary<string, DbParameter> parameters)
        {
            if (clause.Tables.Count == 0)
            {
                throw new QueryException("Invalid from clause, must specify at least one table");
            }

            sb.Append(" FROM ");
            int endSelect = sb.Length;

            foreach (Table table in clause.Tables)
            {
                if (table.JoinedTo == null)
                {
                    GenerateTableName(table, sb);
                    sb.Append(", ");
                }
                else
                {
                    GenerateJoinStatement(table, sb, parameters, endSelect);
                    sb.Append(", ");
                }
            }
            sb.Remove(sb.Length - 2, 2);
        }

        protected virtual void GenerateJoinStatement(Table table, StringBuilder sb, Dictionary<string, DbParameter> parameters, int index)
        {
            GenerateTableName(table, sb);
            bool first = true;

            for(JoinTable jt = table.JoinedTo; jt != null; jt = jt.JoinedTo)
            {
                if (!first)
                {
                    sb.Insert(index, "(");
                    sb.Append(")");
                }
                sb.Append(" ");
                GenerateJoinName(jt.Type, sb);
                sb.Append(" ");
                GenerateTableName(jt, sb);
                if (jt.Condition != null)
                {
                    sb.Append(" ON ");
                    GenerateConditionStatements(jt.Condition, sb, parameters);
                }
                first = false;
            }
        }

        protected virtual void GenerateJoinName(JoinType type, StringBuilder sb)
        {
            switch (type)
            {
                case JoinType.InnerJoin:
                    sb.Append("JOIN");
                    break;
                case JoinType.CrossJoin:
                    sb.Append("CROSS JOIN");
                    break;
                case JoinType.RightOuterJoin:
                    sb.Append("RIGHT JOIN");
                    break;
                case JoinType.LeftOuterJoin:
                    sb.Append("LEFT JOIN");
                    break;
                case JoinType.FullOuterJoin:
                    sb.Append("FULL JOIN");
                    break;
                default:
                    throw new QueryException("Unknown join type");
            }
        }
    }
}
